package mt521.cam.ac.uk;

import java.util.Arrays;

import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.transform.DftNormalization;
import org.apache.commons.math3.transform.FastFourierTransformer;
import org.apache.commons.math3.transform.TransformType;

public class Decode {

    public static double decode(byte[] bTone) {
        double[] dTone = new double[bTone.length];
        for (int i=0; i<bTone.length; i++) {
            dTone[i] = (double)bTone[i];
        }
        double[] transformed = fft(dTone);
        /*double indLower = (double)transformed.length*((double)3985/(Encode.getSampleRate()/2));
        double indHigher = (double)transformed.length*((double)4015/(Encode.getSampleRate()/2));
        int indLow = (int) indLower;
        int indHigh = (int) indHigher;
        System.out.println("Length="+transformed.length);
        System.out.println("Low="+indLow);
        System.out.println("High="+indHigh);
        Arrays.fill(transformed,indLow,indHigh,0.0d);
        Graph.graph(transformed);*/
        int bin = 0;
        for (int i=0; i<transformed.length; i++) {
            bin = transformed[i]>transformed[bin] ? i : bin;
        }
        double frequency = ((double)(bin*Encode.getSampleRate()))/(transformed.length*2);
        return frequency;
    }

    public static double[] fft(double[] input) {
        double[] result = new double[input.length];
        FastFourierTransformer transformer = new FastFourierTransformer(DftNormalization.STANDARD);
        try {
            Complex[] cArray = transformer.transform(input,TransformType.FORWARD);
            for (int i=0; i<cArray.length; i++) {
                double real = (cArray[i].getReal());
                double imag = (cArray[i].getImaginary());
                result[i] = Math.sqrt((real*real) + (imag*imag));
            }
        }
        catch (IllegalArgumentException e) {
            System.err.println("Illegal argument given to FFT in Decode.java");
            e.printStackTrace();
        }

        double[] toReturn = Arrays.copyOf(result,result.length/2);  //only look at the first half as the second is mirror image
        double dIndex = (double)toReturn.length*((double)300/(Encode.getSampleRate()/2));
        int ignoreIndex = (int) dIndex;
        Arrays.fill(toReturn,0,ignoreIndex,0.0d);                    //ignore first 300Hz, background noise overwhelms high freq
        return toReturn;
    }
    
    //contained in decode() but need this seperate for graphing tests
    public static long getFrequency(double[] array) {
        int bin = 0;
        for (int i=0; i<array.length; i++) {
            bin = array[i]>array[bin] ? i : bin;
        }
        double frequency = ((double)(bin*Encode.getSampleRate()))/(array.length*2);
        System.out.print(frequency+" ");
        long solution = 30*(Math.round((frequency)/30));
        return solution;
    }

}